let nbTag = ref []

let color_debug infos color =
  Printf.printf "[%s] %s" color infos;
  print_endline ""

let rec remove_tags note liste =
  let current = note#current_page in
  let currentTextCode = (List.nth !Function._listText current) in
  match liste with
      | [] -> ()
    | e::l -> currentTextCode#buffer#remove_tag_by_name e currentTextCode#buffer#start_iter currentTextCode#buffer#end_iter;
                remove_tags note l

let public_remove_tags note = 
    remove_tags note !nbTag

let get_color line char1 char2 note erase = 
  let current = note#current_page in
  let currentTextCode = (List.nth !Function._listText current) in
  let iterStart = currentTextCode#buffer#get_iter_at_char 
     ~line:line char1 in
  let iterEnd = currentTextCode#buffer#get_iter_at_char 
     ~line:line char2 in
  let _ = currentTextCode#buffer#get_text 
    ~start:iterStart 
    ~stop:iterEnd () in
  begin
  if (erase) then
     remove_tags note !nbTag
  end;
  let sTag = currentTextCode#buffer#create_tag ~name:(string_of_int (line*100+char1*10+char2)) [] in
  nbTag := (string_of_int (line*100+char1*10+char2))::!nbTag;
  sTag#set_property (`BACKGROUND "red");
  currentTextCode#buffer#apply_tag sTag iterStart iterEnd

let parse_compilation_error infos = 
  let rexp_type = Str.regexp "Error: This expression has type .*" in
  let rexp_erro = Str.regexp "Error: .*" in
  let rexp_warn = Str.regexp "Warning: .*" in
  match infos with
    | "Error: Syntax error" -> color_debug "Syntax" "RED"; true
    | "Error: This function is applied to too many arguments;" 
      -> color_debug "Maybe you forgot a ';'" "RED"; true
    | _ as infos ->
      begin
        if (Str.string_match rexp_type infos 0) then
          begin
            color_debug ("Maybe you forgot a parameter"
                          ^"or use the wrong type\n"^infos) "RED";
            true
          end
        else if (Str.string_match rexp_erro infos 0) then
          begin
            color_debug infos "RED";
            true
          end
        else if (Str.string_match rexp_warn infos 0) then
          begin
            color_debug infos "YELLOW";
            true
          end
        else
          (
            false
          )
      end 

let parse_compilation_line infos note = 
  let rexp_line = Str.regexp ".* line \\([0-9]*\\), .*" in 
  let rexp_char = Str.regexp ".* characters \\([0-9]*\\)-\\([0-9]*\\):" in
  if (Str.string_match rexp_line infos 0) then
    begin
      let line = Str.replace_matched "\\1" infos in
      let _ = Str.string_match rexp_char infos 0 in
      let char1 = Str.replace_matched "\\1" infos in
      let _ = Str.string_match rexp_char infos 0 in
      let char2 = Str.replace_matched "\\2" infos in
      Printf.printf "Error at line : %s\nChar : %s - %s\n"
         line char1 char2;
      print_endline "";
      get_color ((int_of_string line)-1) (int_of_string char1)             
        (int_of_string char2) note true
    end

let read_process_args program program_args (item : GSourceView2.source_view) note =
    let _readMe, _outMe = Unix.pipe () in
    ignore(Unix.create_process program program_args (* program [| program; arg1; arg2 |] *)
    Unix.stdin _outMe _outMe);
    Unix.close _outMe;
    let in_channel = Unix.in_channel_of_descr _readMe in
    let lines = ref [] in
    begin
        try
        while true do
          lines := input_line in_channel :: !lines;
          if (parse_compilation_error (List.hd !lines)) then
            parse_compilation_line (List.hd (List.tl !lines)) note;
          item#buffer#set_text ((item#buffer#get_text ())^(List.hd !lines)^"\n")
        done
        with End_of_file -> ()
    end;
    Unix.close _readMe;
    (List.rev !lines)

let read_process_lines command (item : GSourceView2.source_view) =
  let lines = ref [] in
  let in_channel = Unix.open_process_in command in
  begin
    try
      while true do
        lines := input_line in_channel :: !lines;
          item#buffer#set_text ((item#buffer#get_text ())^(List.hd !lines)^"\n")
      done;
    with End_of_file ->
      ignore (Unix.close_process_in in_channel)
  end;
  List.rev !lines

let fork_shell () =
  match Unix.fork () with
    | 0 -> begin
           match Unix.fork () with
            | 0 -> let () = Unix.execv "/bin/sh" 
                [| "/bin/sh" |] in
                 exit 0
            | pid -> exit 0
            end
    | pid ->
        ignore (Unix.waitpid [] pid)

let rec lecture buf (item : GSourceView2.source_view) read =
      try
        while true do 
        let lu = Unix.read read buf 0 1024 in
        if lu < 1024 then
            buf.[lu] <- (Char.chr 0);
        let text = Glib.Utf8.normalize buf `ALL in
        item#buffer#set_text
            ((item#buffer#get_text ())^(text));
        print_endline text;
        done;
      with Unix.Unix_error (a,b,c) -> match a with
        | Unix.EAGAIN -> () (*lecture buf item read*)
        | _ -> print_endline (Unix.error_message a)

let send_shell text (item : GSourceView2.source_view) read writeme =
    let buf = String.make 1024 (Char.chr 0) in 
    match text with
      | "" -> lecture buf item read
      | "exit" -> print_endline "You won't do that."
      | "quit" -> 
            output_string writeme ("quit\n");
            flush writeme
      | text ->
            output_string writeme (text^"\n");
            flush writeme;
            item#buffer#set_text
                ((item#buffer#get_text ())^("\n"));
            lecture buf item read

